home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / networking / pgpuam / sources / tpgpkey.cp < prev    next >
Encoding:
Text File  |  2000-06-23  |  13.1 KB  |  433 lines

  1. //    TPGPkey.cp - PGP Key Object  
  2. // 
  3. // Apple Macintosh Developer Technical Support
  4. // Written by:  Vinnie Moscaritolo
  5. //
  6. //  Copyright (work in progress)  Apple Computer, Inc All rights reserved.
  7. //
  8. // You may incorporate this sample code into your applications without
  9. // restriction, though the sample code has been provided "AS IS" and the
  10. // responsibility for its operation is 100% yours.  However, what you are
  11. // not permitted to do is to redistribute the source as "DSC Sample Code"
  12. // after having made changes. If you're going to re-distribute the source,
  13. // we require that you make it clear in the source that the code was
  14. // descended from Apple Sample Code, but that you've made changes.
  15. // 
  16.  
  17.  
  18. #include <string.h>
  19. #include <TextUtils.h>
  20. #include <PLStringFuncs.h>
  21. #include "TPGPkey.h"
  22. #include "TPGPException.h"
  23.  
  24. #include "pgpRandomPool.h"
  25. #include "pgpUserInterface.h"
  26. #include "pgpPublicKey.h"
  27.  
  28.  
  29.  
  30. // ===========================================================================
  31. //    Static member variables
  32. // ===========================================================================
  33.  
  34. PGPContextRef        TPGPkey::fgContext        = kInvalidPGPContextRef;    //  PGP context
  35. PGPKeySetRef        TPGPkey::fgPGPKeySetRef    = kInvalidPGPKeySetRef;         //  this keyset
  36.  
  37. // ---------------------------------------------------------------------------
  38.  void TPGPkey::Initialize() //  (static public)
  39. // ---------------------------------------------------------------------------
  40. //  Create a new PGP context
  41. {
  42.     if(! PGPContextRefIsValid(fgContext) ) 
  43.         ThrowIfPGPErr( PGPNewContext( kPGPsdkAPIVersion, &fgContext));
  44.  
  45. }
  46.  
  47. // ---------------------------------------------------------------------------
  48.  void TPGPkey::Initialize(PGPMemoryMgrRef memMgr) //  (static public)
  49. // ---------------------------------------------------------------------------
  50. //  Create a ustome PGP context
  51. {
  52.  
  53.     PGPNewContextStruct contextInfo;
  54.  
  55. // Create a custom PGP context
  56.     contextInfo.sizeofStruct =  sizeof( PGPNewContextStruct );
  57.     contextInfo.memoryMgr    =     memMgr;
  58.  
  59.     if(! PGPContextRefIsValid(fgContext) ) 
  60.         ThrowIfPGPErr(  PGPNewContextCustom( kPGPsdkAPIVersion, &contextInfo ,&fgContext));
  61.  
  62. }
  63.  
  64.  
  65.  
  66. // ---------------------------------------------------------------------------
  67.  void TPGPkey::Finalize() //  (static public)
  68. // ---------------------------------------------------------------------------
  69. //  shutdown a new PGP context
  70. {
  71.     if( PGPContextRefIsValid( fgContext)) PGPFreeContext(fgContext );
  72.     fgContext = kInvalidPGPContextRef;
  73.  
  74. }
  75.  
  76. // ---------------------------------------------------------------------------
  77.  void TPGPkey::OpenKeyDefaultRing() //  (static public)
  78. // ---------------------------------------------------------------------------
  79. //  Create a new PGP context
  80. {
  81.     if( PGPContextRefIsValid(fgContext)  
  82.         && ( fgPGPKeySetRef == kInvalidPGPKeySetRef) )
  83.             ThrowIfPGPErr( PGPOpenDefaultKeyRings(fgContext,  0, &fgPGPKeySetRef)) ; 
  84.  }
  85.  
  86.  
  87. // ---------------------------------------------------------------------------
  88.  void TPGPkey::CloseKeyRing() //  (static public)
  89. // ---------------------------------------------------------------------------
  90. //  Create a new PGP context
  91. {
  92.     if( PGPContextRefIsValid(fgContext) && PGPKeySetRefIsValid ( fgPGPKeySetRef ))
  93.         PGPFreeKeySet (fgPGPKeySetRef );
  94.  
  95.     fgPGPKeySetRef = kInvalidPGPKeySetRef;
  96.  }
  97.  
  98.  
  99.  
  100. // ---------------------------------------------------------------------------
  101. void    TPGPkey::Initialize(PGPKeyRef theKey)
  102. // ---------------------------------------------------------------------------
  103. //  
  104. {
  105.     
  106.     if( PGPContextRefIsValid(fgContext)
  107.     /*        && PGPKeySetRefIsValid(fgPGPKeySetRef) */
  108.         && PGPKeyRefIsValid(theKey))
  109.     {
  110.         PGPHashContextRef    theHashRef           = kInvalidPGPHashContextRef;
  111.         PGPInt32            level;
  112.         PGPTime                theTime;
  113.         
  114.         ThrowIfPGPErr( PGPGetKeyNumber (theKey,  kPGPKeyPropAlgID,  (PGPInt32*) &fPublicKeyAlgorithm));
  115.          ThrowIfPGPErr( PGPGetHashAlgUsed (theKey, &fHashAlgorithm) );
  116.          ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsExpired,  &fExpired));
  117.         ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsRevoked,  &fRevoked));
  118.         ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsDisabled, &fDisabled));
  119.         ThrowIfPGPErr( PGPGetKeyBoolean (theKey, kPGPKeyPropIsAxiomatic,&fAxiomatic)) ;
  120.         ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropBits, (PGPInt32*) &fKeySize));
  121.         ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropCreation, &theTime));
  122.         fCreatedTime = PGPTimeToMacTime(theTime);
  123.         ThrowIfPGPErr( PGPGetKeyTime(theKey, kPGPKeyPropExpiration, &theTime));
  124.         fExpireTime = PGPTimeToMacTime(theTime);
  125.     
  126.         ThrowIfPGPErr (PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
  127.         ThrowIfPGPErr (PGPGetHashSize( theHashRef,&fHashSize));
  128.         PGPFreeHashContext(theHashRef);
  129.  
  130.     
  131.         ThrowIfPGPErr( PGPGetPrimaryUserIDValidity(theKey, &fValidity));
  132.  
  133.         ThrowIfPGPErr( PGPGetKeyNumber(theKey, kPGPKeyPropTrust, &level));
  134.         switch(level)
  135.             {
  136.                 default:
  137.                 case kPGPKeyTrust_Undefined:
  138.                 case kPGPKeyTrust_Unknown:
  139.                 case kPGPKeyTrust_Never:
  140.                     fTrustLevel = 0;
  141.                     break;
  142.                 case kPGPKeyTrust_Marginal:
  143.                     fTrustLevel = 1;
  144.                     break;
  145.                 case kPGPKeyTrust_Complete:
  146.                     fTrustLevel = 2;
  147.                     break;
  148.                 case kPGPKeyTrust_Ultimate:
  149.                     fTrustLevel = 3;
  150.                     break;
  151.             }
  152.         fKeyRef = theKey;
  153.         fInitialized = true;
  154.     }
  155.     else
  156.     {
  157.         fKeyRef      = kInvalidPGPKeyRef;
  158.         fInitialized = false;
  159.     }
  160. }
  161.  
  162. // ---------------------------------------------------------------------------
  163. Boolean    TPGPkey::CanSign()
  164. // ---------------------------------------------------------------------------
  165. // key can be used to sign
  166. {
  167.     Boolean result = false;
  168.     
  169.     if( this->IsOperational() )
  170.         ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanSign,  &result));
  171.      
  172.     return result;
  173. }
  174.  
  175. // ---------------------------------------------------------------------------
  176. Boolean    TPGPkey::CanVerify()
  177. // ---------------------------------------------------------------------------
  178. // key can be used to sign
  179. {
  180.     Boolean result = false;
  181.     
  182.     if( this->IsOperational() )
  183.         ThrowIfPGPErr( PGPGetKeyBoolean (fKeyRef, kPGPKeyPropCanVerify,  &result));
  184.      
  185.     return result;
  186. }
  187.  
  188.  
  189. // ---------------------------------------------------------------------------
  190. short    TPGPkey::GetIconID()
  191. // ---------------------------------------------------------------------------
  192. // determine which icon to draw
  193. {
  194.  
  195.     short    iconID = kAlertIcon_ID;
  196.     
  197.     if( fInitialized )
  198.     {
  199.            if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_RSA)
  200.           {
  201.               if( fRevoked) iconID = kIconRSA_Revoked_ID;
  202.               else if(fExpired) iconID = kIconRSA_Expired_ID;
  203.              else if(fDisabled) iconID = kIconRSA_Disabled_ID;
  204.              else iconID = kIconRSA_ID;
  205.           } 
  206.           else if(fPublicKeyAlgorithm == kPGPPublicKeyAlgorithm_DSA)
  207.            {
  208.               if(fRevoked) iconID = kIconDH_RevokedID;
  209.               else if(fExpired) iconID = kIconDH_Expired_ID;
  210.              else if(fDisabled) iconID = kIconDH_Disabled_ID;
  211.              else iconID = kIconDH_ID;
  212.           }
  213.       }
  214.  
  215.     return iconID;
  216. }
  217.  
  218. // ---------------------------------------------------------------------------
  219. void    TPGPkey::GetPrimaryUserNamePString(StringPtr outbuf)
  220. // ---------------------------------------------------------------------------
  221. // 
  222. {
  223.     PGPSize        bufLen;
  224.     char         buffer[256];
  225.  
  226.     ThrowIfPGPErr(PGPGetPrimaryUserIDNameBuffer(fKeyRef, sizeof( buffer) -1 , (char*) &buffer[1], &bufLen ));
  227.  
  228.   // truncate at email address
  229.      buffer[0] =  (strchr(&buffer[1], '<')  - &buffer[1] - 1);
  230.     PLstrcpy(outbuf,(StringPtr) buffer);
  231.     
  232. }
  233.  
  234.  
  235. // ---------------------------------------------------------------------------
  236. void    TPGPkey::GetFingerprintBinaryPString(void* outBuf)
  237. // ---------------------------------------------------------------------------
  238. // 
  239.     PGPSize fpSize;
  240.     unsigned char* p = (unsigned char*) outBuf;
  241.     
  242.     ThrowIfPGPErr( PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, MAX_PGPSize, NULL, &fpSize));
  243.  
  244.     ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, fpSize, &p[1], &fpSize));
  245.     
  246.     p[0] = (fpSize & 0xFF);
  247.  
  248. }
  249.  
  250.  
  251. // ---------------------------------------------------------------------------
  252. void    TPGPkey::GetFingerprintPString(StringPtr outBuf)
  253. // ---------------------------------------------------------------------------
  254. // 
  255. {
  256.     const      char     hexDigit[] = "0123456789ABCDEF";
  257.     PGPSize            bufLen;
  258.     unsigned char    buffer[255];
  259.     int                strIndex;
  260.  
  261.     ThrowIfPGPErr(PGPGetKeyPropertyBuffer( fKeyRef, kPGPKeyPropFingerprint, sizeof( buffer ), buffer, &bufLen));
  262.  
  263.     char *p = (char *) outBuf;
  264.     *p++ = '\0';
  265.     
  266.     if(bufLen == 20)
  267.         {
  268.             for(strIndex = 0 ; strIndex < 20 ; strIndex++)
  269.             {
  270.                 *p++ = hexDigit[buffer[strIndex]>>4];
  271.                 *p++ = hexDigit[buffer[strIndex]&0xF];
  272.                 if((strIndex == 1) || (strIndex == 3) || (strIndex == 5)
  273.                         || (strIndex == 7) || (strIndex == 11) ||
  274.                         (strIndex == 13)
  275.                         || (strIndex == 13) || (strIndex == 15) ||
  276.                         (strIndex == 17))
  277.                     *p++ = ' ';
  278.                 else if(strIndex == 9)
  279.                 {
  280.                      *p++ = ' ';
  281.                      *p++ = ' ';
  282. //                     *p++ = '\r';
  283.                 }
  284.             }
  285.         }
  286.     else
  287.         {
  288.             for(strIndex = 0 ; strIndex < 16 ; strIndex++)
  289.             {
  290.                 *p++ = hexDigit[buffer[strIndex]>>4];
  291.                 *p++ = hexDigit[buffer[strIndex]&0xF];
  292.                 if((strIndex == 1) || (strIndex == 3) || (strIndex == 5)
  293.                     || (strIndex == 9) || (strIndex == 11) || (strIndex == 13))
  294.                     *p++ = ' ';
  295.                 else if(strIndex == 7)
  296.                 {
  297.                     *p++ = ' ';
  298.                     *p++ = ' ';
  299.                 }
  300.             }
  301.         }
  302.     outBuf[0] = (p - (char*)outBuf - 1) & 0xFF;
  303.  
  304. }
  305.  
  306.  
  307. // ---------------------------------------------------------------------------
  308. void    TPGPkey::GetPublicKeyAlgorithmPstring(StringPtr outBuf)
  309. // ---------------------------------------------------------------------------
  310. // 
  311. {
  312.     StringPtr    algStr = "\pUnknown";
  313.         
  314.     if(outBuf)
  315.     {
  316.         if( fInitialized )
  317.             switch(fPublicKeyAlgorithm)
  318.             {
  319.                 case kPGPPublicKeyAlgorithm_Invalid:        algStr = "\pInvalid";  break;
  320.                 case kPGPPublicKeyAlgorithm_RSA:            algStr = "\pRSA";     break;
  321.                 case kPGPPublicKeyAlgorithm_RSAEncryptOnly:    algStr = "\pRSA (Encrypt Only)"; break;
  322.                 case kPGPPublicKeyAlgorithm_RSASignOnly:    algStr = "\pRSA (Sign Only)";     break;
  323.                 case kPGPPublicKeyAlgorithm_ElGamal:         algStr = "\pDiffie-Hellman";         break;
  324.                 case kPGPPublicKeyAlgorithm_DSA:             algStr = "\pDSS";     break;
  325.             }
  326.         PLstrcpy(outBuf,algStr);
  327.     }
  328. }
  329.  
  330.  
  331.  
  332.  
  333.  
  334. // ---------------------------------------------------------------------------
  335. void    TPGPkey::Export(void** buf, PGPSize *bufSize )
  336. // ---------------------------------------------------------------------------
  337. // 
  338. {
  339.     if( this->IsOperational() )
  340.     {
  341.         PGPKeySetRef theKeyset;
  342.         Str255             keyName;
  343.     
  344.         this->GetPrimaryUserNamePString(keyName);
  345.         p2cstr(keyName);
  346.         
  347.         PGPNewSingletonKeySet( fKeyRef,&theKeyset );
  348.         PGPExportKeySet( theKeyset,
  349.                             PGPOAllocatedOutputBuffer    ( fgContext, buf, MAX_PGPUInt32, bufSize ),
  350.                             PGPOArmorOutput    (fgContext, true),
  351. //                             PGPOVersionString    (fgContext, "PGPUAM Version 1.0" ),
  352.                                 PGPOCommentString    (fgContext, (char*) keyName),
  353.                             PGPOLastOption( fgContext ));
  354.                             
  355.         PGPFreeKeySet(theKeyset);
  356.     }
  357.  
  358.  
  359. }
  360.  
  361. // the behaviour of allowing disable keys to verify is questionable.
  362. // PGPTools allows a user to verify and decrypt with keys that have
  363. // been flagged by the user as disabled...BUT It could be argued that
  364. // this is the wroong thing to do in a server authentication environment
  365. // if disagree wit hthis feel free to disable the following define..
  366.  
  367. #define DISABLED_KEYS_CANT_VERIFY 1
  368.  
  369.  
  370. // ---------------------------------------------------------------------------
  371. Boolean    TPGPkey::Verify( void* inbuf, PGPSize inBufSize, void* sigbuf,  PGPSize sigBufSize )
  372. // ---------------------------------------------------------------------------
  373. // 
  374. {
  375.     PGPError err  = kPGPError_BadParams;
  376.     
  377.      if( this->IsOperational()  
  378. #if DISABLED_KEYS_CANT_VERIFY
  379.                  && ! this->IsDisabled()
  380. #endif
  381.            )
  382.     {
  383.         PGPHashContextRef         theHashRef      = kInvalidPGPHashContextRef;
  384.         PGPPublicKeyContextRef    thePublicKeyRef = kInvalidPGPPublicKeyContextRef;
  385.  
  386.         ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
  387.         ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize ));
  388.  
  389.          ThrowIfPGPErr( PGPNewPublicKeyContext(    fKeyRef,
  390.                                                 kPGPPublicKeyMessageFormat_PGP,
  391.                                                  &thePublicKeyRef));
  392.          err = PGPPublicKeyVerifySignature( thePublicKeyRef, theHashRef, sigbuf, sigBufSize) ;
  393.  
  394.           PGPFreePublicKeyContext(thePublicKeyRef);
  395.      }
  396.      
  397.    
  398.     return (err == kPGPError_NoErr) ;
  399.  
  400. }
  401.  
  402.  
  403.  
  404. // ---------------------------------------------------------------------------
  405. Boolean    TPGPkey::Sign( void* inbuf, PGPSize inBufSize, void* sigbuf,  PGPSize *sigBufSize,  const char *passPhrase)
  406. // ---------------------------------------------------------------------------
  407. // 
  408. {
  409.     PGPError err  = kPGPError_BadParams;
  410.  
  411.     if( this->IsOperational() )
  412.     {
  413.  
  414.         PGPHashContextRef         theHashRef          = kInvalidPGPHashContextRef;
  415.         PGPPrivateKeyContextRef thePrivateKeyRef     = kInvalidPGPPrivateKeyContextRef;
  416.  
  417.         ThrowIfPGPErr( PGPNewHashContext( PGPGetContextMemoryMgr(fgContext), fHashAlgorithm, &theHashRef));
  418.         ThrowIfPGPErr( PGPContinueHash( theHashRef,inbuf, inBufSize ));
  419.  
  420.         err =  PGPNewPrivateKeyContext(    fKeyRef, kPGPPublicKeyMessageFormat_PGP, &thePrivateKeyRef,
  421.                                             PGPOPassphrase( fgContext, passPhrase),
  422.                                             PGPOLastOption( fgContext ));
  423.         if(err == kPGPError_NoErr)
  424.         {     
  425.         ThrowIfPGPErr( PGPPrivateKeySign( thePrivateKeyRef, theHashRef, sigbuf, sigBufSize ));
  426.         PGPFreePrivateKeyContext(thePrivateKeyRef);
  427.         }
  428.     }
  429.  
  430.     return (err == kPGPError_NoErr) ;
  431.  }
  432.